home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Blender 2.49b / blender-2.49b-windows.exe / $_4_ / .blender / scripts / bpymodules / BPyWindow.py < prev    next >
Text File  |  2009-08-31  |  7KB  |  206 lines

  1. import Blender
  2. from Blender import Mathutils, Window, Scene, Draw, Mesh
  3. from Blender.Mathutils import Matrix, Vector, Intersect
  4.  
  5. # DESCRIPTION:
  6. # screen_x, screen_y the origin point of the pick ray
  7. # it is either the mouse location
  8. # localMatrix is used if you want to have the returned values in an objects localspace.
  9. #    this is usefull when dealing with an objects data such as verts.
  10. # or if useMid is true, the midpoint of the current 3dview
  11. # returns
  12. # Origin - the origin point of the pick ray
  13. # Direction - the direction vector of the pick ray
  14. # in global coordinates
  15. epsilon = 1e-3 # just a small value to account for floating point errors
  16.  
  17. def mouseViewRay(screen_x, screen_y, localMatrix=None, useMid = False):
  18.     
  19.     # Constant function variables
  20.     p = mouseViewRay.p
  21.     d = mouseViewRay.d
  22.     
  23.     for win3d in Window.GetScreenInfo(Window.Types.VIEW3D): # we search all 3dwins for the one containing the point (screen_x, screen_y) (could be the mousecoords for example) 
  24.         win_min_x, win_min_y, win_max_x, win_max_y = win3d['vertices']
  25.         # calculate a few geometric extents for this window
  26.  
  27.         win_mid_x  = (win_max_x + win_min_x + 1.0) * 0.5
  28.         win_mid_y  = (win_max_y + win_min_y + 1.0) * 0.5
  29.         win_size_x = (win_max_x - win_min_x + 1.0) * 0.5
  30.         win_size_y = (win_max_y - win_min_y + 1.0) * 0.5
  31.  
  32.         #useMid is for projecting the coordinates when we subdivide the screen into bins
  33.         if useMid: # == True
  34.             screen_x = win_mid_x
  35.             screen_y = win_mid_y
  36.         
  37.         # if the given screencoords (screen_x, screen_y) are within the 3dwin we fount the right one...
  38.         if (win_max_x > screen_x > win_min_x) and (  win_max_y > screen_y > win_min_y):
  39.             # first we handle all pending events for this window (otherwise the matrices might come out wrong)
  40.             Window.QHandle(win3d['id'])
  41.             
  42.             # now we get a few matrices for our window...
  43.             # sorry - i cannot explain here what they all do
  44.             # - if you're not familiar with all those matrices take a look at an introduction to OpenGL...
  45.             pm    = Window.GetPerspMatrix()   # the prespective matrix
  46.             pmi  = Matrix(pm); pmi.invert() # the inverted perspective matrix
  47.             
  48.             if (1.0 - epsilon < pmi[3][3] < 1.0 + epsilon):
  49.                 # pmi[3][3] is 1.0 if the 3dwin is in ortho-projection mode (toggled with numpad 5)
  50.                 hms = mouseViewRay.hms
  51.                 ortho_d = mouseViewRay.ortho_d
  52.                 
  53.                 # ortho mode: is a bit strange - actually there's no definite location of the camera ...
  54.                 # but the camera could be displaced anywhere along the viewing direction.
  55.                 
  56.                 ortho_d.x, ortho_d.y, ortho_d.z = Window.GetViewVector()
  57.                 ortho_d.w = 0
  58.                 
  59.                 # all rays are parallel in ortho mode - so the direction vector is simply the viewing direction
  60.                 #hms.x, hms.y, hms.z, hms.w = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
  61.                 hms[:] = (screen_x-win_mid_x) /win_size_x, (screen_y-win_mid_y) / win_size_y, 0.0, 1.0
  62.                 
  63.                 # these are the homogenious screencoords of the point (screen_x, screen_y) ranging from -1 to +1
  64.                 p=(hms*pmi) + (1000*ortho_d)
  65.                 p.resize3D()
  66.                 d[:] = ortho_d[:3]
  67.                 
  68.  
  69.             # Finally we shift the position infinitely far away in
  70.             # the viewing direction to make sure the camera if outside the scene
  71.             # (this is actually a hack because this function
  72.             # is used in sculpt_mesh to initialize backface culling...)
  73.             else:
  74.                 # PERSPECTIVE MODE: here everything is well defined - all rays converge at the camera's location
  75.                 vmi  = Matrix(Window.GetViewMatrix()); vmi.invert() # the inverse viewing matrix
  76.                 fp = mouseViewRay.fp
  77.                 
  78.                 dx = pm[3][3] * (((screen_x-win_min_x)/win_size_x)-1.0) - pm[3][0]
  79.                 dy = pm[3][3] * (((screen_y-win_min_y)/win_size_y)-1.0) - pm[3][1]
  80.                 
  81.                 fp[:] = \
  82.                 pmi[0][0]*dx+pmi[1][0]*dy,\
  83.                 pmi[0][1]*dx+pmi[1][1]*dy,\
  84.                 pmi[0][2]*dx+pmi[1][2]*dy
  85.                 
  86.                 # fp is a global 3dpoint obtained from "unprojecting" the screenspace-point (screen_x, screen_y)
  87.                 #- figuring out how to calculate this took me quite some time.
  88.                 # The calculation of dxy and fp are simplified versions of my original code
  89.                 #- so it's almost impossible to explain what's going on geometrically... sorry
  90.                 
  91.                 p[:] = vmi[3][:3]
  92.                 
  93.                 # the camera's location in global 3dcoords can be read directly from the inverted viewmatrix
  94.                 #d.x, d.y, d.z =normalize_v3(sub_v3v3(p, fp))
  95.                 d[:] = p.x-fp.x, p.y-fp.y, p.z-fp.z
  96.                 
  97.                 #print 'd', d, 'p', p, 'fp', fp
  98.                 
  99.             
  100.             # the direction vector is simply the difference vector from the virtual camera's position
  101.             #to the unprojected (screenspace) point fp
  102.             
  103.             # Do we want to return a direction in object's localspace?
  104.             
  105.             if localMatrix:
  106.                 localInvMatrix = Matrix(localMatrix)
  107.                 localInvMatrix.invert()
  108.                 localInvMatrix_notrans = localInvMatrix.rotationPart()
  109.                 p = p * localInvMatrix
  110.                 d = d * localInvMatrix # normalize_v3
  111.                 
  112.                 # remove the translation from d
  113.                 d.x -= localInvMatrix[3][0]
  114.                 d.y -= localInvMatrix[3][1]
  115.                 d.z -= localInvMatrix[3][2]
  116.                 
  117.             
  118.             d.normalize()            
  119.             '''
  120.             # Debugging
  121.             me = Blender.Mesh.New()
  122.             me.verts.extend([p[0:3]])
  123.             me.verts.extend([(p-d)[0:3]])
  124.             me.edges.extend([0,1])
  125.             ob = Blender.Scene.GetCurrent().objects.new(me)
  126.             '''
  127.             return True, p, d # Origin, Direction    
  128.     
  129.     # Mouse is not in any view, return None.
  130.     return False, None, None
  131.  
  132. # Constant function variables
  133. mouseViewRay.d = Vector(0,0,0) # Perspective, 3d
  134. mouseViewRay.p = Vector(0,0,0)
  135. mouseViewRay.fp = Vector(0,0,0)
  136.  
  137. mouseViewRay.hms = Vector(0,0,0,0) # ortho only 4d
  138. mouseViewRay.ortho_d = Vector(0,0,0,0) # ortho only 4d
  139.  
  140.  
  141. LMB= Window.MButs['L']
  142. def mouseup():
  143.     # Loop until click
  144.     mouse_buttons = Window.GetMouseButtons()
  145.     while not mouse_buttons & LMB:
  146.         Blender.sys.sleep(10)
  147.         mouse_buttons = Window.GetMouseButtons()
  148.     while mouse_buttons & LMB:
  149.         Blender.sys.sleep(10)
  150.         mouse_buttons = Window.GetMouseButtons()
  151.  
  152.  
  153. if __name__=='__main__':
  154.     mouseup()
  155.     x,y= Window.GetMouseCoords()
  156.     isect, point, dir= mouseViewRay(x,y)
  157.     if isect:
  158.         scn= Blender.Scene.GetCurrent()
  159.         me = Blender.Mesh.New()
  160.         ob= Blender.Object.New('Mesh')
  161.         ob.link(me)
  162.         scn.link(ob)
  163.         ob.sel= 1
  164.         me.verts.extend([point, dir])
  165.         me.verts[0].sel= 1
  166.         
  167.     print isect, point, dir
  168.     
  169.     
  170.  
  171. def spaceRect():
  172.     '''
  173.     Returns the space rect
  174.     xmin,ymin,width,height
  175.     '''
  176.     
  177.     __UI_RECT__ = Blender.BGL.Buffer(Blender.BGL.GL_FLOAT, 4)
  178.     Blender.BGL.glGetFloatv(Blender.BGL.GL_SCISSOR_BOX, __UI_RECT__) 
  179.     __UI_RECT__ = __UI_RECT__.list
  180.     __UI_RECT__ = int(__UI_RECT__[0]), int(__UI_RECT__[1]), int(__UI_RECT__[2])-1, int(__UI_RECT__[3]) 
  181.     
  182.     return __UI_RECT__
  183.  
  184. def mouseRelativeLoc2d(__UI_RECT__= None):
  185.     if not __UI_RECT__:
  186.         __UI_RECT__ = spaceRect()
  187.     
  188.     mco = Window.GetMouseCoords()
  189.     if    mco[0] > __UI_RECT__[0] and\
  190.     mco[1] > __UI_RECT__[1] and\
  191.     mco[0] < __UI_RECT__[0] + __UI_RECT__[2] and\
  192.     mco[1] < __UI_RECT__[1] + __UI_RECT__[3]:
  193.     
  194.         return (mco[0] - __UI_RECT__[0], mco[1] - __UI_RECT__[1])
  195.         
  196.     else:
  197.         return None
  198.     
  199.  
  200.  
  201.  
  202.     
  203.  
  204.  
  205.  
  206.